package Analizadores.Utilidades;

import java.util.HashMap;

import Analizadores.AnalizadorLexico.CategoriaLexica;
import Analizadores.AnalizadorSintactico.Tipos;


enum TIPO_OP {solo_entero,coincide,todos_real,siempre_entero,siempre_real,asignacion};
/*todos real = si los dos son enteros devuelve entero sino devuelve real4
solo entero =  es unario, entra entero y devuelve entero
coincide = devuelve lo ke entra
siempre entero = devuelve entero siempre
siempre real = devuelve real siempre
*/

// Clase para comprobar el tipado de las operaciones
public class Comprobaciones {
	private HashMap<CategoriaLexica, TIPO_OP> comp;
	
	public Comprobaciones(){
		comp = new HashMap<CategoriaLexica,TIPO_OP>();

		//operadores de lectura/escritura
		comp.put(CategoriaLexica.CLIN, TIPO_OP.coincide);
		comp.put(CategoriaLexica.CLOUT, TIPO_OP.coincide);
		//operadores de comparacion
		comp.put(CategoriaLexica.CLMENOR, TIPO_OP.siempre_entero);
		comp.put(CategoriaLexica.CLMAYOR, TIPO_OP.siempre_entero);
		comp.put(CategoriaLexica.CLMENORIG, TIPO_OP.siempre_entero);
		comp.put(CategoriaLexica.CLMAYORIG, TIPO_OP.siempre_entero);
		comp.put(CategoriaLexica.CLIGUAL, TIPO_OP.siempre_entero);
		comp.put(CategoriaLexica.CLDISTINTO, TIPO_OP.siempre_entero);
		//operadores aritmeticos binarios(+,-,*,/)
		comp.put(CategoriaLexica.CLSUMA, TIPO_OP.todos_real);
		comp.put(CategoriaLexica.CLRESTA, TIPO_OP.todos_real); //tambien cambio de signo
		comp.put(CategoriaLexica.CLMUL, TIPO_OP.todos_real);
		comp.put(CategoriaLexica.CLDIV, TIPO_OP.todos_real);
		//operadores logicos binarios
		comp.put(CategoriaLexica.CLAND, TIPO_OP.solo_entero);
		comp.put(CategoriaLexica.CLOR, TIPO_OP.solo_entero);
		//modulo
		comp.put(CategoriaLexica.CLMOD, TIPO_OP.solo_entero);
		//negacion logica !
		comp.put(CategoriaLexica.CLNEG, TIPO_OP.solo_entero);
		//conversion a entero
		comp.put(CategoriaLexica.CLCASTENT, TIPO_OP.siempre_entero);
		//conversion a real
		comp.put(CategoriaLexica.CLCASTREAL, TIPO_OP.siempre_real);	
		//asignacion
		comp.put(CategoriaLexica.CLASIG, TIPO_OP.asignacion);
	}
	
	public Tipos daResultado(CategoriaLexica operacion,Tipos tipo1,Tipos tipo2){ //operaciones con dos operandos
		
		TIPO_OP aux = comp.get(operacion);//obtenemos el tipo de operacion para devolver el tipo que devuelve la operacion
		
		if(aux == TIPO_OP.siempre_entero){
			return Tipos.entero;
		}
		else if(aux == TIPO_OP.todos_real){
			if((tipo1==tipo2) && (tipo1==Tipos.entero)){
				return Tipos.entero;
			}
			else 
				return Tipos.real;
		}
		else if(aux == TIPO_OP.solo_entero){
			if((tipo1==tipo2)&&(tipo1==Tipos.entero)) return Tipos.entero;
			else return Tipos.error;
		}
		else if(aux == TIPO_OP.asignacion){
			if(tipo1==Tipos.real) return Tipos.real;
			else if((tipo1==Tipos.entero)&&(tipo2==Tipos.entero)) return Tipos.entero;
			else return Tipos.error;
		}
		else return Tipos.error;
	}
	public Tipos daResultado(CategoriaLexica operacion,Tipos Tipo){ //operaciones con un operando
		TIPO_OP aux = comp.get(operacion);
		
		if(aux == TIPO_OP.coincide){
			return Tipo;	
		}
		else if (aux == TIPO_OP.siempre_entero){
			return Tipos.entero;
		}
		else if(aux == TIPO_OP.siempre_real){
			return Tipos.real;
		}
		else if(aux == TIPO_OP.solo_entero){
			if(Tipo==Tipos.entero) return Tipos.entero;
			else return Tipos.error;
		}
		else if(aux == TIPO_OP.todos_real){ //operacion cambio de signo
			return Tipo;
		}
		else return Tipos.error;
		
	}
	
	
}